"""
Base Extension Interface

Defines the abstract base class that all GSM extensions must implement.
"""

from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional
from pathlib import Path
from .base_runner import BaseRunner


class BaseExtension(ABC):
    """
    Abstract base class for all GSM extensions.
    
    Extensions provide support for different solver frameworks by implementing
    binary execution logic.
    """
    
    def __init__(self, name: str, version: str = "1.0.0"):
        """
        Initialize the extension.
        
        Args:
            name: Unique name for the extension
            version: Extension version string
        """
        self._name = name
        self._version = version
        self._enabled = True
        
    @property
    def name(self) -> str:
        """Get the extension name."""
        return self._name
        
    @property  
    def version(self) -> str:
        """Get the extension version."""
        return self._version
        
    @property
    def enabled(self) -> bool:
        """Check if extension is enabled."""
        return self._enabled
        
    def enable(self) -> None:
        """Enable the extension."""
        self._enabled = True
        
    def disable(self) -> None:
        """Disable the extension."""
        self._enabled = False
    
    @property
    @abstractmethod
    def description(self) -> str:
        """Get a brief description of the extension."""
        pass
        
    @property
    @abstractmethod
    def supported_frameworks(self) -> List[str]:
        """Get list of supported framework names."""
        pass
        
    @property
    @abstractmethod
    def config_schema(self) -> Dict[str, Any]:
        """Get JSON schema for extension configuration."""
        pass
    
    @abstractmethod
    def can_handle_config(self, config_path: str) -> bool:
        """
        Check if this extension can handle the given configuration.
        
        Args:
            config_path: Path to configuration file
            
        Returns:
            True if extension can handle this configuration
        """
        pass
    
    @abstractmethod
    def run_binary(self, config_path: Path) -> bool:
        """
        Execute binary with given configuration.
        
        Args:
            config_path: Path to configuration file
            
        Returns:
            True if execution succeeded, False otherwise
        """
        pass
    
    def initialize(self) -> None:
        """
        Initialize the extension (called after loading).
        Override to perform custom initialization.
        """
        pass
        
    def cleanup(self) -> None:
        """
        Clean up extension resources (called before unloading).
        Override to perform custom cleanup.
        """
        pass
    
    def get_commands(self) -> Dict[str, Any]:
        """
        Get custom CLI commands provided by this extension.
        
        Returns:
            Dictionary mapping command names to command definitions
        """
        return {}
    
    def validate_environment(self) -> List[str]:
        """
        Validate that the environment meets extension requirements.
        
        Returns:
            List of error messages (empty if valid)
        """
        return []
    
    def get_dependencies(self) -> List[str]:
        """
        Get list of other extensions this extension depends on.
        
        Returns:
            List of extension names
        """
        return []
    
    def get_config_descriptor(self) -> Optional[Dict[str, Any]]:
        """
        Get configuration descriptor for config-driven extensions.
        
        This method is optional and only needed for extensions that want to
        define their build/test/validation logic through configuration files
        instead of pure Python code.
        
        Returns:
            Configuration descriptor dictionary or None for Python-based extensions
        """
        return None
    
    def __str__(self) -> str:
        """String representation of the extension."""
        return f"{self.name} v{self.version}"
        
    def __repr__(self) -> str:
        """Detailed string representation."""
        return f"<{self.__class__.__name__}(name='{self.name}', version='{self.version}', enabled={self.enabled})>"


class SolverExtension(BaseExtension):
    """
    Base class for solver-specific extensions.
    
    Simplified to focus only on binary execution without build complexity.
    """
    
    def __init__(self, name: str, version: str = "1.0.0"):
        """Initialize the solver extension."""
        super().__init__(name, version)
    
    @property
    @abstractmethod
    def supported_frameworks(self) -> List[str]:
        """Get list of supported framework names."""
        pass
        
    @property
    def config_schema(self) -> Dict[str, Any]:
        """Get JSON schema for configuration (simplified)."""
        return {
            "type": "object",
            "properties": {
                "binary_path": {"type": "string"},
                "mpi_processes": {"type": "integer", "default": 1},
                "log_file": {"type": "string"}
            },
            "required": ["binary_path"]
        }